if(!window.Berta) window.Berta = {};

Berta.Panel = new Class(function(){
    return {
		
		statics: {
	    	_instance: null, // Singleton instance
			instance: function(options) {
				if(!Berta.Panel._instance) {
					Berta.Panel._instance = new Berta.Panel(options);
				}
				
				return Berta.Panel._instance;
			},
	    	
	    	paneDefinitions: {},
			addPaneDefinition: function(name, paneClass) {
				this.paneDefinitions[name] = paneClass;
			}
		},
		
		
		options: {},
		defaults: {
			maxPaneHeight: 260
		},
		
		// getter: returns event namespace for the instance
		namespace: function() { return '.Berta.Panel'; },
		
		// DOM elements
		container: null,
		accordion: null,
	
		// panes
		panes: null,
		panesArray: null,
		currentOpenedPaneIndex: false,
		
		
		constructor: function(options) {
			this.options = $.extend(true, {}, this.defaults, options);
			this._(build)();
			this.enable();
		},

		//   .______    __    __  .______    __       __    ______    ////////////////////////////////////////////////////////////
		//   |   _  \  |  |  |  | |   _  \  |  |     |  |  /      |   ////////////////////////////////////////////////////////////
		//   |  |_)  | |  |  |  | |  |_)  | |  |     |  | |  ,----'   ////////////////////////////////////////////////////////////
		//   |   ___/  |  |  |  | |   _  <  |  |     |  | |  |        ////////////////////////////////////////////////////////////
		//   |  |      |  `--'  | |  |_)  | |  `----.|  | |  `----.   ////////////////////////////////////////////////////////////
		//   | _|       \______/  |______/  |_______||__|  \______|   ////////////////////////////////////////////////////////////

		enable: function() {
			for(var i = 0; i < this.panesArray.length; i++)
				this.panesArray[i].enableInteraction();
		},

		open: function(paneType) {
			if(!paneType) paneType = 'contextual';
			if(this.panesByType[paneType]) {
				this.panesByType[paneType].open();
			}
		},
		close: function() {
			//this.accordion.accordion('activate', false);
		},
		closeOthers: function (paneType) {
			for (var i = 0; i < this.panesArray.length; i++) {
				if(this.panesArray[i].type != paneType && this.panesArray[i].type != 'contextual') {
					this.panesArray[i].close();
				}
			}
		},
		destroy: function() {
			for(var i = 0; i < this.panesArray.length; i++)
				this.panesArray[i].destroy();

			this.panesContainer.empty().remove();
			this.container.remove();
			this.panesContainer = null;
			this.container = null;
		},


		showContext: function(settings) {
			this.contextualPane.contextOn(settings);
		},
		hideContext: function() {
			this.contextualPane.contextOff();
		}



    };
	
	
	
	
	
	//   .______   .______     __  ____    ____  ___   .___________. _______    //////////////////////////////////////////////////
	//   |   _  \  |   _  \   |  | \   \  /   / /   \  |           ||   ____|   //////////////////////////////////////////////////
	//   |  |_)  | |  |_)  |  |  |  \   \/   / /  ^  \ `---|  |----`|  |__      //////////////////////////////////////////////////
	//   |   ___/  |      /   |  |   \      / /  /_\  \    |  |     |   __|     //////////////////////////////////////////////////
	//   |  |      |  |\  \--.|  |    \    / /  _____  \   |  |     |  |____    //////////////////////////////////////////////////
	//   | _|      | _| `.___||__|     \__/ /__/     \__\  |__|     |_______|   //////////////////////////////////////////////////
	
	
	function build() {
		this.container = $('<div id="xBertaPanel" class="x-panel">' +
					'<div class="x-panel-head"></div>' +
				'</div>');
		this.panesContainer = $('<div class="x-panes"></div>').appendTo(this.container);

		
		this.panesArray = [];
		this.panes = {};
		var pD = this.statics.paneDefinitions, paneHTML;
		for(var defName in pD) {
			if(pD.hasOwnProperty(defName)) {
				this.panes[defName] = new pD[defName]({
					type: defName,
					index: this.panesArray.length,
					
					callbacks: {
						onOpenStart: this._(onPaneOpenStart),
						onOpen: this._(onPaneOpen),
						onCloseStart: this._(onPaneCloseStart),
						onClose: this._(onPaneClose),
						onLock: this._(onPaneLock),
						onUnlock: this._(onPaneUnlock),
						onResize: this._(onPaneResize)
					}
				});
				
				if(defName == 'contextual') this.contextualPane = this.panes[defName];
				
				this.panesArray.push(this.panes[defName]);
				this.panesContainer.append(this.panes[defName].elements.head)
								   .append(this.panes[defName].elements.body);
			}
		}

		// Add live events for foldable pane subheadings
		$('.x-pane-subheading-foldable').live('click', function() {
			$(this).toggleClass('x-pane-subheading-folded');
		});

		// Place in the position where the visitor left it the last time
		this._(build_restorePosition)();

		// Add panel to DOM
		$(document.body).append(this.container);

		this._(build_resizing)();
		this._(build_dragging)();
	}

	function build_restorePosition() {
		var p;
		if(p = jQuery.cookie('panel_position_1_left')) {
			this.container.css('left', p + 'px').css('right', 'auto');
		}

		if(p = jQuery.cookie('panel_position_1_top')) {
			this.container.css('top', p + 'px');
		}
	}
	function build_resizing() {
		// Panel resizing
		//$.log(this.panesContainer.height());
		this.container.resizable({
			minWidth: 290,
			maxWidth: 290,
			minHeight: this.panesContainer.height(),
			handles: 'se',
			resize: this._(onPanelContainerResize)
		});
	}
	function build_dragging() {
		// Instead of dragging by pane titles, just allow dragging by the header strip
		this.container.draggable({
			handle: this.container.find('.x-panel-head'),
			containment: 'document',
			stop: function(e, ui){
				// Save position in a cookie, for retrieval upon page reload
				var pos = {
					left: parseInt($(e.target).css('left')),
					top: parseInt($(e.target).css('top'))
				};

				//$.log('panel_position', pos, { 'path': Berta.URLBase.files + '/' });
				jQuery.cookie('panel_position_1_left', pos.left, { 'path': Berta.URLBase.files + '/' });
				jQuery.cookie('panel_position_1_top', pos.top, { 'path': Berta.URLBase.files + '/' });
			}
		});
	}






	function onPaneOpenStart(paneType) {
		// close all other panes
		if(paneType != 'contextual') {
			this.closeOthers(paneType);
		}
	}
	function onPaneOpen(paneType) {
		
	}
	function onPaneCloseStart(paneType) {
		
	}
	function onPaneClose(paneType) {
		
	}
	function onPaneLock(paneType) {
		// prevent other panes from opening
		for(var i=0; i < this.panesArray.length; i++) {
			if(this.panesArray[i].type != paneType) {
				if(this.panesArray[i].isOpen) {
					this.panesArray[i].close();
				}
				this.panesArray[i].disableInteraction();
			}
		}
	}
	function onPaneUnlock(paneType) {
		// re-enable opening of other panes
		for(var i=0; i < this.panesArray.length; i++) {
			if(this.panesArray[i].type != paneType) {
				this.panesArray[i].enableInteraction();
			}
		}
	}
	
	
	function onPaneResize(paneType) {
		//$.log('Panel: pane ' + paneType + ' resize');
		var h = this.panes[paneType].getContentHeight();

		if(h > this.options.maxPaneHeight) h = this.options.maxPaneHeight;
		this.panes[paneType].setHeight(h);
		
		this.container.css('height', 'auto');
					  //.resizable('option', 'minHeight', this.panesContainer.height());
	}
	function onPanelContainerResize() {
		var hPanes = this.panesContainer.height();
		var hC = this.container.height();
		var i;
		var hDif = hC - hPanes;
		
		//console.debug('--------------------------', hDif);
		if (hDif > 0) {
			var paneNeeds = [], 
				totalHeightNeed = 0, numPanesOpen = 0,
				spaceAvailForNeedy = 0, eachOpenCanHave = 0;
			
			// collect the needs from all panes
			for (i = 0; i < this.panesArray.length; i++) {
				paneNeeds[i] = this.panesArray[i].getNeededHeight();
				//console.debug(this.panesArray[i].type, paneNeeds[i]);
				totalHeightNeed += paneNeeds[i];
				numPanesOpen += this.panesArray[i].isOpen ? 1 : 0;
			}
			
			if(totalHeightNeed > 0) {
				// the given space will be equal of that needed, if not bigger than total space aquired by resize
				spaceAvailForNeedy = Math.min(totalHeightNeed, hDif);
				// convert paneNeeds to coefficients by which to multiply spaceAvailForNeedy
				for(i = 0; i < paneNeeds.length; i++) paneNeeds[i] /= totalHeightNeed;
			}
			
			// if we have more space than needed, then distribute it equally to all open panes
			eachOpenCanHave = (hDif - totalHeightNeed > 0) ? (hDif - totalHeightNeed) / numPanesOpen : 0;
			
			for (i = 0; i < this.panesArray.length; i++) {
				if(paneNeeds[i] > 0) {
					// if pane needs space, then give a weighted fraction of the avialable space
					// plus any surplus space that is given to all open panes
					this.panesArray[i].heightAdd(paneNeeds[i] * spaceAvailForNeedy + eachOpenCanHave);
					//$.log('give to NEEDY ', this.panesArray[i].type, ' ', paneNeeds[i], ', ', paneNeeds[i] * spaceForNeedy + eachOpenCanHave);
				} else if(this.panesArray[i].isOpen && eachOpenCanHave) {
					// if there's space for everyone, then give it!
					this.panesArray[i].heightAdd(eachOpenCanHave);
					//$.log('give to open ', this.panesArray[i].type, ' ', eachOpenCanHave);
				}
			}
			
		} else if(hDif < 0) {
			
			var paneSurpluses = [],
				totalHeightSurplus = 0, numPanesOpen = 0,
				spaceNeededFromRich = 0;
			
			// collect the surpluses from all panes
			for (i = 0; i < this.panesArray.length; i++) {
				paneSurpluses[i] = this.panesArray[i].getSurplusHeight();
				//console.debug(this.panesArray[i].type, paneSurpluses[i]);
				totalHeightSurplus += paneSurpluses[i];
				numPanesOpen += this.panesArray[i].isOpen ? 1 : 0;
			}
			
			
			if(totalHeightSurplus > 0) {
				// first take all away from the rich
				
				spaceNeededFromRich = Math.min(totalHeightSurplus, -hDif);
				//for(i = 0; i < paneSurpluses.length; i++) paneSurpluses[i] /= totalHeightSurplus;
				// take from every surplused rich pane a weighted fraction of the available space
				for (i = 0; i < this.panesArray.length; i++) {
					if(paneSurpluses[i] > 0) {
						this.panesArray[i].heightAdd(-paneSurpluses[i] / totalHeightSurplus * spaceNeededFromRich);
						//$.log('take away from RICH ', this.panesArray[i].type, -paneSurpluses[i] / totalHeightSurplus * spaceNeededFromRich)
					}
				}
			}
			
			if(-hDif > totalHeightSurplus) {
				// need to take also from the poor
				var spaceNeededFromPoor = totalHeightSurplus - hDif,
					paneHeights = [], totalPaneHeight = 0;
					
				for (i = 0; i < this.panesArray.length; i++) {
					if(this.panesArray[i].isOpen) {
						paneHeights[i] = this.panesArray[i].elements.body.height();
						totalPaneHeight += paneHeights[i];
					}
				}
				
				// take away from the poor pane a weighted fraction of the change in the panel size
				if(totalPaneHeight > 0) {
					for (i = 0; i < this.panesArray.length; i++) {
						if(this.panesArray[i].isOpen) {
							this.panesArray[i].heightAdd(-(paneHeights[i] / totalPaneHeight) * spaceNeededFromPoor);
							//$.log('take away from POOR ', this.panesArray[i].type, paneHeights[i], -(1 - paneHeights[i] / totalPaneHeight) * spaceNeededFromPoor)
						}
					}
				}
			}
		}
	}
	

	
	
}());

